---
image: /generated/articles-docs-renderer-render-media.png
id: render-media
title: renderMedia()
crumb: '@remotion/renderer'
---

_Available since v3.0 - Part of the `@remotion/renderer` package._

Render a video or an audio programmatically.

```tsx twoslash title="render.mjs"
const serveUrl = '/path/to/bundle';
const outputLocation = '/path/to/frames';

import {renderMedia, selectComposition} from '@remotion/renderer';

const inputProps = {
  titleText: 'Hello World',
};

const composition = await selectComposition({
  serveUrl,
  id: 'my-video',
  inputProps,
});

// ---cut---

await renderMedia({
  composition,
  serveUrl,
  codec: 'h264',
  outputLocation,
  inputProps,
});
```

See an [example](/docs/ssr-node) of `renderMedia()` together with [`bundle()`](/docs/bundle) and [`selectComposition()`](/docs/renderer/select-composition) on the [server-side rendering page](/docs/ssr-node).

## Arguments

An object with the following properties:

### `serveUrl`

_string_

Either a local path pointing to a Remotion Webpack bundle generated by [`bundle()`](/docs/bundle) or a URL where the bundle is hosted.

### `port?`

Prefer a specific port that will be used to serve the Remotion project. If not specified, a random port will be used.

### `outputLocation?`

_string - optional since v3.0.26_

Where to save the output artifact to. Either an absolute path or a relative path that will be resolved relative to the current working directory. Must be a file path (not a folder).

If not specified or set to `null`, the file will be returned in-memory as a buffer.

### `composition`

_VideoConfig_

An object describing a composition using `id`, `width`, `height`, `fps` and `durationInFrames`, `defaultProps` and `props`.  
Call [`selectComposition()`](/docs/renderer/select-composition) or [`getCompositions()`](/docs/renderer/get-compositions) to get an array of possible configs.

### `codec`

_"h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif"_

Choose a suitable codec for your output media. Refer to the [Encoding guide](/docs/encoding) to find the best codec for your use case.

### `inputProps?`

_object - optional_

[Input Props to pass to the selected composition of your video.](/docs/passing-props#passing-input-props-in-the-cli).  
Must be a JSON object.  
From the root component the props can be read using [`getInputProps()`](/docs/get-input-props).  
You may transform input props using [`calculateMetadata()`](/docs/calculate-metadata).

Make sure to also pass the same `inputProps` to [`selectComposition()`](/docs/renderer/select-composition) for this to work correctly.

### `frameRange?`

_number | [number, number] - optional_

Specify a single frame (passing a `number`) or a range of frames (passing a tuple `[number, number]`) to be rendered. By passing `null` (default) all frames of a composition get rendered.

### `concurrency?`

_optional_

A `number` specifying how many render processes should be started in parallel, a `string` specifying the percentage of the CPU threads to use (e.g. `50%`), or `null` to let Remotion decide based on the CPU of the host machine. Default is half of the CPU threads available.

### `metadata?`<AvailableFrom v="4.0.216" />

_object - optional_

<Options id="metadata" />

### `logLevel?`<AvailableFrom v="4.0.0"/>

<Options id="log" />

### `onArtifact?`<AvailableFrom v="4.0.176" />

[Handle an artifact](/docs/artifacts#using-rendermedia-renderstill-or-renderframes) that was emitted by the [`<Artifact>`](/docs/artifact) component.

### `audioCodec?`

_"pcm-16" | "aac" | "mp3" | "opus", available from v3.3.41_

Choose the encoding of your audio.

- The default is dependent on the chosen `codec`.
- Choose `pcm-16` if you need uncompressed audio.
- Not all video containers support all audio codecs.
- This option takes precedence if the `codec` option also specifies an audio codec.

Refer to the [Encoding guide](/docs/encoding/#audio-codec) to see defaults and supported combinations.

### `audioBitrate?`<AvailableFrom v="3.2.32" />

<Options id="audio-bitrate" />

### `videoBitrate?`<AvailableFrom v="3.2.32" />

<Options id="video-bitrate" />

### `crf?`

_number | null - optional_

The constant rate factor, controlling the quality. See: [Controlling quality using the CRF setting.](/docs/encoding/#controlling-quality-using-the-crf-setting)

### `bufferSize?`<AvailableFrom v="4.0.78" />

<Options id="buffer-size" />

### `maxRate?`<AvailableFrom v="4.0.78" />

<Options id="max-rate" />

### `imageFormat?`

_"jpeg" (default) | "png" | "none" - optional since v3.2.27_

In which image format the frames should be rendered.

- `jpeg` is the default and is fastest
- `png` if you want to [render transparent videos](/docs/transparent-videos/)
- `none` if you are rendering audio

### `browserExecutable?`<AvailableFrom v="3.0.11" />

_optional_

A string defining the absolute path on disk of the browser executable that should be used. By default Remotion will try to detect it automatically and download one if none is available. If `puppeteerInstance` is defined, it will take precedence over `browserExecutable`.

### `everyNthFrame?`<AvailableFrom v="3.1.0" />

_optional_

Renders only every nth frame. For example only every second frame, every third frame and so on. Only works for rendering GIFs. [See here for more details.](/docs/render-as-gif)

### `numberOfGifLoops?`<AvailableFrom v="3.1.0" />

_optional_

<Options id="number-of-gif-loops" />

### `pixelFormat?`

_string - optional_

[A custom pixel format to use.](/docs/transparent-videos/) Usually used for special use cases like transparent videos.

### `envVariables?`

`Record<string, string> - optional`

An object containing environment variables to be injected in your project.

See: [Environment variables](/docs/env-variables/)

### `jpegQuality?`

_number - optional_

Sets the quality of the generated JPEG images. Must be an integer between 0 and 100. Default is to leave it up to the browser, [current default is 80](https://github.com/chromium/chromium/blob/99314be8152e688bafbbf9a615536bdbb289ea87/headless/lib/browser/protocol/headless_handler.cc#L32).

Only applies if `imageFormat` is `'jpeg'`, otherwise this option is invalid.

### `muted?`<AvailableFrom v="3.2.1" />

_boolean - optional_

If set to true, no audio is being rendered.

### `hardwareAcceleration?`<AvailableFrom v="4.0.228" />

<Options id="hardware-acceleration" />

### `enforceAudioTrack?`<AvailableFrom v="3.2.1" />

_boolean - optional_

Render a silent audio track if there wouldn't be any otherwise.

### `puppeteerInstance?`

_puppeteer.Browser - optional_

An already open [`Browser`](/docs/renderer/open-browser) instance. Use [`openBrowser()`](/docs/renderer/open-browser) to create a new instance. Reusing a browser across multiple function calls can speed up the rendering process. You are responsible for opening and closing the browser yourself. If you don't specify this option, a new browser will be opened and closed at the end.

:::note
Despite the name, not actually compatible with `puppeteer`, only with [`openBrowser()`](/docs/renderer/open-browser).
:::

### `scale?`

_optional_

Scales the output dimensions by a factor. See [Scaling](/docs/scaling) to learn more about this feature.

### `overwrite?`

_boolean - optional_

If set to false, the output file will not be written if a file already exists.

### `onStart?`

_function_ - optional

Callback function that gets called once the renderer has prepared to start rendering and has calculated the amount of frames that are going to be rendered:

```tsx twoslash
import {OnStartData} from '@remotion/renderer';

const onStart = ({
  frameCount,
  parallelEncoding, // available from v4.0.52
  resolvedConcurrency, // available from v4.0.180
}: OnStartData) => {
  console.log(`Beginning to render ${frameCount}.`);

  if (parallelEncoding) {
    console.log('Parallel encoding is enabled.');
  }

  console.log(`Using concurrency: ${resolvedConcurrency}`);
};
```

### `onProgress?`

_function - optional_

React to render progress. The following callback function is similar to how Remotion displays render progress on it's CLI:

```tsx twoslash title="Simple example - Log overall progress"
import {RenderMediaOnProgress} from '@remotion/renderer';

const onProgress: RenderMediaOnProgress = ({progress}) => {
  console.log(`Rendering is ${progress * 100}% complete`);
};
```

```tsx twoslash title="Advanced example - Fine-grained progress values"
import {RenderMediaOnProgress} from '@remotion/renderer';

const onProgress: RenderMediaOnProgress = ({renderedFrames, encodedFrames, encodedDoneIn, renderedDoneIn, stitchStage}) => {
  if (stitchStage === 'encoding') {
    // First pass, parallel rendering of frames and encoding into video
    console.log('Encoding...');
  } else if (stitchStage === 'muxing') {
    // Second pass, adding audio to the video
    console.log('Muxing audio...');
  }
  // Amount of frames rendered into images
  console.log(`${renderedFrames} rendered`);
  // Amount of frame encoded into a video
  console.log(`${encodedFrames} encoded`);
  // Time to create images of all frames
  if (renderedDoneIn !== null) {
    console.log(`Rendered in ${renderedDoneIn}ms`);
  }
  // Time to encode video from images
  if (encodedDoneIn !== null) {
    console.log(`Encoded in ${encodedDoneIn}ms`);
  }
};
```

:::note
The `progress` attribute is available from v3.2.17.
:::

### `onDownload?`

_function - optional_

If an audio (or a video with sound) is included in your project, Remotion needs to download it in order to use it's audio in the output file. You can use this callback to react to a download happening and progressing.

```tsx twoslash
import {RenderMediaOnDownload} from '@remotion/renderer';

const onDownload: RenderMediaOnDownload = (src) => {
  console.log(`Downloading ${src}...`);
  return ({percent, downloaded, totalSize}) => {
    // percent and totalSize can be `null` if the downloaded resource
    // does not have a `Content-Length` header
    if (percent === null) {
      console.log(`${downloaded} bytes downloaded`);
    } else {
      console.log(`${Math.round(percent * 100)}% done)`);
    }
  };
};
```

### `proResProfile?`

_string - optional_

Sets a ProRes profile. Only applies to videos rendered with `prores` codec. See [Encoding guide](/docs/encoding/#controlling-quality-using-prores-profile) for possible options.

### `x264Preset?`

_string - optional_

<Options id="x264-preset" />

### `onBrowserLog?`

_function - optional_

Catch a console message being printed. Example:

```tsx twoslash
import {BrowserLog} from '@remotion/renderer';

const onBrowserLog = (log: BrowserLog) => {
  // `type` is the console.* method: `log`, `warn`, `error`, etc.
  console.log(`[${log.type}]`);
  console.log(log.text);
  console.log(`at ${log.stackTrace}`);
};
```

### `timeoutInMilliseconds?`

_optional_

A number describing how long the render may take to resolve all [`delayRender()`](/docs/delay-render) calls [before it times out](/docs/timeout). Default: `30000`

### `cancelSignal?`<AvailableFrom v="3.0.15" />

_optional_

A token that allows the render to be cancelled. See: [`makeCancelSignal()`](/docs/renderer/make-cancel-signal)

### `chromiumOptions?`<AvailableFrom v="2.6.5" />

_optional_

Allows you to set certain Chromium / Google Chrome flags. See: [Chromium flags](/docs/chromium-flags).

:::note
Chromium flags need to be set at browser launch. If you pass an instance using [`puppeteerInstance`](#puppeteerinstance), options passed to `renderMedia()` will not apply, but rather the flags that have been passed to [`openBrowser()`](/docs/renderer/open-browser).
:::

#### `disableWebSecurity?`

_boolean - default `false`_

This will most notably disable CORS among other security features.

#### `enableMultiProcessOnLinux?`<AvailableFrom v="4.0.42" />

_boolean - default `true`_

<Options id="enable-multiprocess-on-linux" />

#### `ignoreCertificateErrors?`

_boolean - default `false`_

Results in invalid SSL certificates, such as self-signed ones, being ignored.

#### ~`headless?`~

<Options id="disable-headless" />

#### `gl?`

<Options id="gl" />

### `chromeMode?`<AvailableFrom v="4.0.248" />

<Options id="chrome-mode" />

#### `userAgent?`<AvailableFrom v="3.3.83"/>

Lets you set a custom user agent that the headless Chrome browser assumes.

### `ffmpegOverride?`<AvailableFrom v="3.2.22" />

_function - optional_

Modifies the FFMPEG command that Remotion uses under the hood. It works reducer-style, meaning that you pass a function that takes a command as an argument and returns a new command.

```tsx twoslash
import type {FfmpegOverrideFn} from '@remotion/renderer';

const ffmpegOverride: FfmpegOverrideFn = ({type, args}) => {
  console.log(type); // "stitcher" | "pre-stitcher
  return [...args, '-vf', 'eq=brightness=0:saturation=1'];
};
```

The function you pass must accept an object as it's only parameter which contains the following properties:

- `type`: Either `"stitcher"` or `"pre-stitcher"`. If enough memory and CPU is available, Remotion may use a two-pass process for the video generation. `pre-stitcher` is the encoding phase and `stitcher` is the muxing phase. If the override function is only called once with `stitcher`, then encoding and muxing is done in the same step. You can tell whether parallel encoding is enabled by adding `--log=verbose` to your render command.
- `args`: An array of strings that is passed as arguments to the FFMPEG command.

Your function must return a modified array of strings.

:::warning
Using this feature is discouraged. Before using it, we want to make you aware of some caveats:

- The render command can change with any new Remotion version, even when it is a patch upgrade. This might break your usage of this feature.
- Depending on the selected codec, available CPU and RAM, Remotion may or may not use "parallel encoding" which will result in multiple FFMPEG commands being executed. Your function must be able to handle being called multiple times.
- This feature is not available when using Remotion Lambda.

Before you use this hack, reach out to the Remotion team on [Discord](https://remotion.dev/discord) and ask us if we are open to implement the feature you need in a clean way - we often do implement new features quickly based on users feedback.
:::

### `disallowParallelEncoding?`<AvailableFrom v="3.2.29" />

Disallows the renderer from doing rendering frames and encoding at the same time. This makes the rendering process more memory-efficient, but possibly slower.

### `mediaCacheSizeInBytes?`<AvailableFrom v="4.0.352"/>

<Options id="media-cache-size-in-bytes" />

### `offthreadVideoCacheSizeInBytes?`<AvailableFrom v="4.0.23"/>

<Options id="offthreadvideo-cache-size-in-bytes" />

### `offthreadVideoThreads?`<AvailableFrom v="4.0.261"/>

<Options id="offthreadvideo-video-threads" />

### `colorSpace?`<AvailableFrom v="4.0.28"/>

<Options id="color-space" />

### `repro?`<AvailableFrom v="4.0.88" />

_boolean - default `false`_

<Options id="repro" />

### `binariesDirectory?`<AvailableFrom v="4.0.120" />

<Options id="binaries-directory" />

### `separateAudioTo?`<AvailableFrom v="4.0.123" />

<Options cli id="separate-audio-to" />

### `forSeamlessAacConcatenation?`<AvailableFrom v="4.0.123" />

<Options id="for-seamless-aac-concatenation" />

### `compositionStart?`<AvailableFrom v="4.0.279"/>

An option to be used only if implementing a distributed renderer, see [Distributed rendering](/docs/distributed-rendering#2-invoking-render-functions) for what to set it to.

### `onBrowserDownload?`<AvailableFrom v="4.0.137" />

<Options id="on-browser-download" />

### `apiKey?`<AvailableFrom v="4.0.375"/>

<Options id="api-key" />

### ~~`parallelism?`~~

Renamed to `concurrency` in v3.2.17.
Removed in `v4.0.0`.

### ~~`quality?`~~

Renamed to `jpegQuality` in `v4.0.0`.

### ~~`dumpBrowserLogs?`~~

_optional - default `false`, deprecated in v4.0_

Deprecated in favor of [`logLevel`](#loglevel).

### ~~`verbose?`~~

_optional, deprecated in v4.0_

Deprecated in favor of [`logLevel`](#loglevel).

### ~~`onSlowestFrames?`~~

Introduced in v3.2.29, removed from v4.0. `slowestFrames` has been moved to the return type.

Callback function that gets called right before `renderMedia()` resolves.  
The only argument `slowestFrames` is an array of the 10 slowest frames in the shape of `{frame:<Frame number>, time:<Time to render frame ms>}`. You can use this information to optimise your render times.

### ~~`ffmpegExecutable`~~

_removed in v4.0, string, optional_

An absolute path overriding the `ffmpeg` executable to use.

### ~~`ffprobeExecutable?`~~ <AvailableFrom v="3.0.17" />

_removed in v4.0, optional_

An absolute path overriding the `ffprobe` executable to use.

## Return Value

_**from v4.0.0:**_

The return value is an object with the following properties:

- `buffer`: If `outputLocation` is not specified or `null`, contains a buffer, otherwise `null`.
- `slowestFrames`: An array of the 10 slowest frames in the shape of `{frame:<Frame number>, time:<Time to render frame ms>}`. You can use this information to optimise your render times.

_**from v3.0.26**:_

If `outputLocation` is not specified or `null`, the return value is a Promise that resolves a `Buffer`. If an output location is specified, the return value is a Promise that resolves no value.

## See also

- [Source code for this function](https://github.com/remotion-dev/remotion/blob/main/packages/renderer/src/render-media.ts)
- [Server-Side rendering](/docs/ssr)
- [getCompositions()](/docs/renderer/get-compositions)
- [renderStill()](/docs/renderer/stitch-frames-to-video)
- [renderMediaOnLambda()](/docs/lambda/rendermediaonlambda)
